#pragma once
#include "elisa/elisa.h"
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <gaol/gaol>

#include "Modeler.h"

#ifdef ELISA_PERFORMER
#include "elisa_chrono.h"
#endif

using namespace std;
using namespace elisa;

/* 3D configurations of the cyclo-hexane molecule

@unpublished{BiniMourrain1996,
author    = {D. Bini and B. Mourrain},
title     = {{Handbook} of {Polynomial} {Systems}},
month     = {November},
year      = {1996}
}
*/
class Cyclohexane : public Modeler
{
private:
	Model _model;

	RealVar x;
	RealVar y;
	RealVar z;
	RealConstraint c1;
	RealConstraint c2;
	RealConstraint c3;

public:
	Cyclohexane()
		: x(Interval(-1.0e8,1.0e8), "x"),
		  y(Interval(-1.0e8,1.0e8), "y"),
		  z(Interval(-1.0e8,1.0e8), "z"),
		  c1(13+pow(y,2)*(1+pow(z,2))+z*(z-24*y) == 0),
		  c2(13+pow(z,2)*(1+pow(x,2))+x*(x-24*z) == 0),
		  c3(13+pow(x,2)*(1+pow(y,2))+y*(y-24*x) == 0),
		  _model()
	{
	}

	elisa::Model & model()
	{
		_model = c1 && c2 && c3;
		return _model;
	}

	void print()
	{
		cout << '\t' << x.getName() << " = " << x.domain() << endl;
		cout << '\t' << y.getName() << " = " << y.domain() << endl;
		cout << '\t' << z.getName() << " = " << z.domain() << endl;
	}

	RealVar & varX()
	{
		return x;
	}
	RealVar & varY()
	{
		return y;
	}
};
